package com.joker.aigc.chat.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Pair;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.joker.aigc.chat.dao.ContactDao;
import com.joker.aigc.chat.domain.dto.ContactQueryCriteria;
import com.joker.aigc.chat.domain.entity.Contact;
import com.joker.aigc.chat.domain.entity.Message;
import com.joker.aigc.chat.domain.entity.Room;
import com.joker.aigc.chat.domain.entity.RoomGroup;
import com.joker.aigc.domain.entity.User;
import com.joker.aigc.chat.domain.enums.RoomTypeEnum;
import com.joker.aigc.chat.domain.mapstruct.ContactMapstruct;
import com.joker.aigc.chat.domain.vo.ContactVo;
import com.joker.aigc.chat.mapper.ContactMapper;
import com.joker.aigc.chat.service.ContactService;
import com.joker.aigc.chat.service.MessageService;
import com.joker.aigc.chat.service.RoomFriendService;
import com.joker.aigc.chat.service.RoomGroupService;
import com.joker.aigc.chat.service.RoomService;
import com.joker.aigc.service.UserService;
import com.joker.aigc.chat.service.strategy.AbstractMsgHandler;
import com.joker.aigc.chat.service.strategy.MsgHandlerFactory;
import com.joker.aigc.utils.AssertUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author 20346
 * @description 针对表【message(消息表)】的数据库操作Service实现
 * @createDate 2023-12-17 11:26:08
 */
@Slf4j
@Transactional
@RequiredArgsConstructor
@Service
public class ContactServiceImpl extends ServiceImpl<ContactMapper, Contact> implements ContactService {


    final ContactMapstruct contactMapstruct;

    final RoomService roomService;
    final RoomFriendService roomFriendService;
    final RoomGroupService roomGroupService;
    final UserService userService;
    final MessageService messageService;
    final ContactDao contactDao;

    /**
     * 查出用户要展示的会话列表
     *
     * @param uid      用户id
     * @param criteria 查询条件
     * @return 该用户的会话列表
     */
    @Override
    public Page<ContactVo> getRoomPage(Long uid, ContactQueryCriteria criteria) {

        Page<Contact> queryPage = new Page<Contact>(criteria.getPageNum(), criteria.getPageSize());
        // 首先根据分页情况 找出 该用户的 会话情况
        Page<Contact> contactPage = baseMapper.selectPage(queryPage, new LambdaQueryWrapper<Contact>().eq(Contact::getUid, uid));
        long total = contactPage.getTotal();
        List<Contact> contactList = contactPage.getRecords();
        Page<ContactVo> result = new Page<>(criteria.getPageNum(), criteria.getPageSize(), total);
        // 获
        if (CollectionUtil.isNotEmpty(contactList)) {
            // step 1: 根据 会话的id  找出房间信息。
            List<Long> roomIds = contactList.stream().map(Contact::getRoomId).collect(Collectors.toList());
            result.setRecords(buildContactResp(uid, roomIds));
        } else {
            // 如果空空荡荡，则返回热门数据
            List<Room> hotRoom = roomService.getHotRoom();
            if (CollectionUtil.isNotEmpty(hotRoom)) {
                result.setRecords(buildContactResp(uid, hotRoom.stream().map(Room::getId).collect(Collectors.toList())));
            }
        }
        if (CollectionUtil.isEmpty(result.getRecords())) {
            result.setRecords(new ArrayList<>());
        }
        return result;
    }

    public List<ContactVo> buildContactResp(Long uid, List<Long> roomIds) {

        List<Room> rooms = roomService.listByIds(roomIds);
        Map<Integer, List<Long>> groupRoomIdMap = rooms.stream().collect(Collectors.groupingBy(Room::getType,
                Collectors.mapping(Room::getId, Collectors.toList())));
        Map<Long, Room> roomMap = rooms.stream().collect(Collectors.toMap(Room::getId, item -> item));
        // step 2: 根据 房间号 找出 对应的群组 和单聊 的信息
        List<Long> groupRoomIds = groupRoomIdMap.get(RoomTypeEnum.GROUP.getId());
        Map<Long, RoomGroup> roomInfoBatch = new HashMap<>();
        if (CollectionUtil.isNotEmpty(groupRoomIds)) {
            List<RoomGroup> groupRooms = roomGroupService.listByRoomIds(groupRoomIds);
            roomInfoBatch = groupRooms.stream().collect(Collectors.toMap(RoomGroup::getRoomId, item -> item));
        }

        // 找到 单聊群体消息
        List<Long> friendRoomId = groupRoomIdMap.get(RoomTypeEnum.FRIEND.getId());
        Map<Long, User> friendRoomMap = roomFriendService.getFriendRoomMap(friendRoomId, uid);

        // step 3: 获取最后一条消息
        List<Long> lastMsgIds = rooms.stream().map(Room::getLastMsgId).filter(Objects::nonNull).collect(Collectors.toList());
        Map<Long, Message> messageMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(lastMsgIds)) {
            List<Message> messageList = messageService.listByIds(lastMsgIds);
            messageMap = messageList.stream().collect(Collectors.toMap(Message::getId, item -> item));
        }


        // step 4: 获取未读消息
        Map<Long, Integer> unReadCountMap = getUnReadCountMapByIds(uid, roomIds);
        // 设置
        Map<Long, Message> finalMessageMap = messageMap;
        Map<Long, RoomGroup> finalRoomInfoBatch = roomInfoBatch;

        return roomMap.values().stream().map(room -> {
            ContactVo contactVo = new ContactVo();
            // 如果对象为空的话。
            if (Objects.isNull(room.getLastMsgId())) {
                contactVo.setText("目前为双方未发送消息");
            } else {
                Message message = finalMessageMap.get(room.getLastMsgId());
                AbstractMsgHandler strategyNoNull = MsgHandlerFactory.getStrategyNoNull(message.getType());
                contactVo.setText(strategyNoNull.showContactMsg(message));
            }
            contactVo.setActiveTime(room.getActiveTime());
            contactVo.setRoomId(room.getId());
            contactVo.setType(room.getType());
            contactVo.setHot_Flag(room.getHotFlag());
            if (RoomTypeEnum.of(room.getType()) == RoomTypeEnum.GROUP) {
                RoomGroup roomGroup = finalRoomInfoBatch.get(room.getId());
                contactVo.setAvatar(roomGroup.getAvatar());
                contactVo.setName(roomGroup.getName());
            } else if (RoomTypeEnum.of(room.getType()) == RoomTypeEnum.FRIEND) {
                User user = friendRoomMap.get(room.getId());
                contactVo.setName(user.getUsername());
                contactVo.setAvatar(user.getAvatar());
            }
            contactVo.setUnreadCount(unReadCountMap.getOrDefault(room.getId(), 0));
            return contactVo;
        }).collect(Collectors.toList());
    }


    /**
     * 根据房间号 获取 每个房间的未读总数
     *
     * @param uid      用户id
     * @param contacts 用户
     * @return
     */
    public Map<Long, Integer> getUnReadCountMap(Long uid, List<Contact> contacts) {
        if (Objects.isNull(uid)) {
            return new HashMap<>();
        }
        return contacts.parallelStream()
                .map(contact -> Pair.of(contact.getRoomId(), messageService.getUnReadCount(contact.getRoomId(), contact.getReadTime())))
                .collect(Collectors.toMap(Pair::getKey, Pair::getValue));
    }

    /**
     * @param uid     用戶ids
     * @param roomIds
     * @return
     */
    public Map<Long, Integer> getUnReadCountMapByIds(Long uid, List<Long> roomIds) {
        if (Objects.isNull(uid)) {
            return new HashMap<>();
        }
        List<Contact> contacts = contactDao.getByRoomIds(roomIds, uid);
        return contacts.parallelStream()
                .map(contact -> Pair.of(contact.getRoomId(), messageService.getUnReadCount(contact.getRoomId(), contact.getReadTime())))
                .collect(Collectors.toMap(Pair::getKey, Pair::getValue));
    }


    @Override
    public ContactVo getContactDetail(Long uid, Long roomId) {
        Room room = roomService.getById(roomId);
        AssertUtil.isNotEmpty(room, "房间号为空");
        return buildContactResp(uid, Collections.singletonList(roomId)).get(0);
    }

    @Override
    public ContactVo getContactDetailByFriend(Long uid, Long friendId) {
        return null;
    }

}




